use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, NotSet, PaginatorTrait, QueryFilter};
use sea_orm::ActiveValue::Set;

use common::ctx::get_db;
use common::error::MyError;
use common::page::{BasePage, PageResult};
use entity::{role, role_resource, user_role};
use entity::prelude::{Role, RoleResource, UserRole};
use model::role::{CreateRole, RolePage};

use crate::manager::base::BaseManager;

pub struct RoleManager {}

impl BaseManager<i64, role::Model, RolePage, CreateRole, role::Model> for RoleManager {
    async fn list() -> Result<Vec<role::Model>, MyError> {
        let res = Role::find().all(&*get_db()?).await?;
        Ok(res)
    }

    async fn page(role_page: RolePage) -> Result<PageResult<role::Model>, MyError> {
        let mut page_data = role_page.get_page_data();
        //校验分页数据是否合法
        page_data = page_data.check();
        let mut find = Role::find();
        if let Some(role_name) = role_page.role_name {
            find = find.filter(role::Column::RoleName.like(role_name))
        }
        if let Some(role_code) = role_page.role_code {
            find = find.filter(role::Column::RoleCode.like(role_code))
        }
        if let Some(desc) = role_page.desc {
            find = find.filter(role::Column::Desc.like(desc))
        }
        let db_conn = &*get_db()?;
        let paginator = find.paginate(db_conn, page_data.page_size);

        //分页查询
        let record = paginator.fetch_page(page_data.page - 1).await?;
        //总条数
        let total = paginator.num_items().await?;
        //返回分页结果
        Ok(PageResult {
            page: page_data.page,
            page_size: page_data.page_size,
            total,
            record,
        })
    }

    async fn info(id: i64) -> Result<Option<role::Model>, MyError> {
        let res = Role::find_by_id(id).one(&*get_db()?).await?;
        Ok(res)
    }

    async fn add(form: CreateRole) -> Result<i64, MyError> {
        let role_name = form
            .role_name
            .ok_or(MyError::ServerError("角色名称不能为空".to_string()))?;
        RoleManager::check_role_role_name_exist(role_name.clone()).await?;
        let role_code = form
            .role_code
            .ok_or(MyError::ServerError("角色编码不能为空".to_string()))?;
        RoleManager::check_role_role_code_exist(role_code.clone()).await?;
        let model = role::ActiveModel {
            id: NotSet,
            role_name: Set(role_name),
            role_code: Set(role_code),
            desc: Set(form.desc),
        }
        .insert(&*get_db()?)
        .await?;
        Ok(model.id)
    }

    async fn update(form: role::Model) -> Result<i64, MyError> {
        let entity =
            Role::find_by_id(form.id)
                .one(&*get_db()?)
                .await?
                .ok_or(MyError::ServerError(format!(
                    "user [{:?}] does not exist",
                    form.id
                )))?;
        let mut entity: role::ActiveModel = entity.into();
        let role_name = Option::from(form.role_name);
        if role_name.is_some() {
            RoleManager::check_role_role_name_exist_and_id_ne(role_name.clone().unwrap(), form.id)
                .await?;
            entity.role_name = Set(role_name.unwrap());
        }
        if let Some(role_code) = Option::from(form.role_code) {
            RoleManager::check_role_role_code_exist_and_id_ne(role_code.clone(), form.id).await?;
            entity.role_code = Set(role_code);
        }

        if form.desc.is_some() {
            entity.desc = Set(form.desc);
        }

        let result = entity.update(&*get_db()?).await?;
        Ok(result.id)
    }

    async fn delete(id: i64) -> Result<bool, MyError> {
        let res = Role::delete_by_id(id).exec(&*get_db()?).await?;
        Ok(res.rows_affected == 1)
    }
}

impl RoleManager {
    async fn delete_role_resource_by_role_id(role_id: i64) -> Result<bool, MyError> {
        Ok(role_resource::Entity::delete_many()
            .filter(role_resource::Column::RoleId.eq(role_id))
            .exec(&*get_db()?)
            .await?
            .rows_affected
            > 0)
    }

    pub async fn get_role_list_by_ids(ids: Vec<i64>) -> Result<Vec<role::Model>, MyError> {
        let roles = Role::find()
            .filter(role::Column::Id.is_in(ids))
            .all(&*get_db()?)
            .await?;
        Ok(roles)
    }

    pub async fn get_role_list_by_uid(uid: i64) -> Result<Vec<role::Model>, MyError> {
        let user_role_list = UserRole::find()
            .filter(user_role::Column::UserId.eq(uid))
            .all(&*get_db()?)
            .await?;
        let mut role_ids = Vec::new();
        for user_role_item in user_role_list {
            role_ids.push(user_role_item.role_id);
        }
        let res = RoleManager::get_role_list_by_ids(role_ids).await?;
        Ok(res)
    }

    pub async fn get_role_ids_by_uid(uid: i64) -> Result<Vec<i64>, MyError> {
        let roles = RoleManager::get_role_list_by_uid(uid).await?;
        let mut role_ids = Vec::new();
        for role_item in roles {
            role_ids.push(role_item.id)
        }
        Ok(role_ids)
    }

    pub async fn get_resource_ids_by_role_ids(role_ids: Vec<i64>) -> Result<Vec<i64>, MyError> {
        let user_resource_list = RoleResource::find()
            .filter(role_resource::Column::RoleId.is_in(role_ids))
            .all(&*get_db()?)
            .await?;
        let mut role_id_list = Vec::new();
        for user_resource_item in user_resource_list {
            role_id_list.push(user_resource_item.resource_id);
        }
        Ok(role_id_list)
    }

    pub async fn set_role_resource(resource_ids: Vec<i64>, role_id: i64) -> Result<bool, MyError> {
        if resource_ids.is_empty() {
            Ok(RoleManager::delete_role_resource_by_role_id(role_id).await?)
        } else {
            RoleManager::delete_role_resource_by_role_id(role_id).await?;
            for resource_id in resource_ids {
                role_resource::ActiveModel {
                    id: NotSet,
                    role_id: Set(role_id),
                    resource_id: Set(resource_id),
                }
                .insert(&*get_db()?)
                .await?;
            }
            Ok(true)
        }
    }

    pub async fn set_user_role(uid: i64, role_ids: Vec<i64>) -> Result<bool, MyError> {
        if role_ids.is_empty() {
            Ok(RoleManager::delete_user_role_by_uid(uid).await?)
        } else {
            RoleManager::delete_role_resource_by_role_id(uid).await?;
            for role_id in role_ids {
                user_role::ActiveModel {
                    id: NotSet,
                    role_id: Set(role_id),
                    user_id: Set(uid),
                }
                .insert(&*get_db()?)
                .await?;
            }
            Ok(true)
        }
    }

    async fn delete_user_role_by_uid(uid: i64) -> Result<bool, MyError> {
        Ok(user_role::Entity::delete_many()
            .filter(user_role::Column::UserId.eq(uid))
            .exec(&*get_db()?)
            .await?
            .rows_affected
            > 0)
    }

    pub async fn exist_by_role_name(role_name: String) -> Result<bool, MyError> {
        let exist = Role::find()
            .filter(role::Column::RoleName.eq(role_name))
            .all(&*get_db()?)
            .await?
            .len()
            > 0;
        Ok(exist)
    }

    pub async fn exist_by_role_name_and_id_ne(role_name: String, id: i64) -> Result<bool, MyError> {
        let exist = Role::find()
            .filter(role::Column::RoleName.eq(role_name))
            .filter(role::Column::Id.ne(id))
            .all(&*get_db()?)
            .await?
            .len()
            > 0;
        Ok(exist)
    }

    pub async fn exist_by_role_code(role_code: String) -> Result<bool, MyError> {
        let exist = Role::find()
            .filter(role::Column::RoleCode.eq(role_code))
            .all(&*get_db()?)
            .await?
            .len()
            > 0;
        Ok(exist)
    }

    pub async fn exist_by_role_code_and_id_ne(role_code: String, id: i64) -> Result<bool, MyError> {
        let exist = Role::find()
            .filter(role::Column::RoleCode.eq(role_code))
            .filter(role::Column::Id.ne(id))
            .all(&*get_db()?)
            .await?
            .len()
            > 0;
        Ok(exist)
    }

    pub async fn check_role_role_name_exist(role_name: String) -> Result<String, MyError> {
        if RoleManager::exist_by_role_name(role_name.clone()).await? {
            Err(MyError::ServerError(format!("角色名[{}]已存在", role_name)))
        } else {
            Ok(role_name)
        }
    }

    pub async fn check_role_role_code_exist(role_code: String) -> Result<String, MyError> {
        if RoleManager::exist_by_role_code(role_code.clone()).await? {
            Err(MyError::ServerError(format!(
                "角色编码[{}]已存在",
                role_code
            )))
        } else {
            Ok(role_code)
        }
    }

    pub async fn check_role_role_name_exist_and_id_ne(
        role_name: String,
        id: i64,
    ) -> Result<String, MyError> {
        if RoleManager::exist_by_role_name_and_id_ne(role_name.clone(), id).await? {
            Err(MyError::ServerError(format!("角色名[{}]已存在", role_name)))
        } else {
            Ok(role_name)
        }
    }

    pub async fn check_role_role_code_exist_and_id_ne(
        role_code: String,
        id: i64,
    ) -> Result<String, MyError> {
        if RoleManager::exist_by_role_code_and_id_ne(role_code.clone(), id).await? {
            Err(MyError::ServerError(format!(
                "角色编码[{}]已存在",
                role_code
            )))
        } else {
            Ok(role_code)
        }
    }
}
